/**
 * 利用 AnimationFrame 实现的 setRAFTimeout
 * @param callback 回调函数
 * @param delay 延迟时间（毫秒）(可选)
 */
export function setRAFTimeout(callback: Function, delay?: number) {
  const start = performance.now()
  const _delay = delay ? delay : 0

  function loop(timestamp: number) {
    const elapsed = timestamp - start

    if (elapsed > _delay) {
      // console.log('执行')
      callback()
    } else {
      requestAnimationFrame(loop)
    }
  }
  requestAnimationFrame(loop)
}

/**
 * 利用 AnimationFrame 实现的 throttle 节流函数 和 防抖函数
 * @param callback 执行函数
 * @param params 补充条件 leading: 立即开始 delay: 延迟开始
 * @returns
 */
export function throttleRAF<T extends (..._args: any[]) => void>(
  callback: T,
  params: { leading?: boolean; delay?: number },
) {
  let throttleId: number | null = null
  let start: number | null = null
  const _delay = params.delay ? params.delay : 0

  const resetThrottle = (cancel: boolean, args?: Parameters<T>) => {
    if (throttleId) {
      cancelAnimationFrame(throttleId)
      throttleId = null
    }
    if (cancel) return
    throttleId = requestAnimationFrame((timeStamp: number) => {
      if (start === null) throw Error('Start is null')
      const elapsed = timeStamp - start

      if (elapsed > _delay) {
        // console.log('执行 resetThrottle')
        args && callback(...args)
        start = timeStamp
      } else {
        // 如果未达到延迟时间，重新调度
        resetThrottle(false, args)
      }
    })
  }

  const throttleFn = (...args: Parameters<T>) => {
    if (params.leading && throttleId === null) {
      // 立马执行
      callback(...args)
    }
    if (start === null) {
      start = performance.now()
    }
    resetThrottle(false, args)
  }

  // 外部主动调用的 cancel 方法
  throttleFn.cancel = () => {
    resetThrottle(true)
    start = null
  }

  throttleFn.debounce = (...args: Parameters<T>) => {
    if (params.leading && throttleId === null) {
      // 立马执行
      callback(...args)
    }
    start = performance.now()
    resetThrottle(false, args)
  }

  return throttleFn
}
